#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/signal.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <unistd.h>

#include "../include/queries.h"
#include "../databaseADT/databaseADT.h"
#include "../../common/include/common.h"
#include "../../common/include/general.h"
#include "../../common/include/split.h"
#include "../../common/include/menu.h"
#include "../include/server.h"

#include "../include/pipeserver.h"
#include "../../common/include/commonPI.h"

int fdpub = -1;
char * fifo = "/tmp/public";

/* Externs de server.c */
extern char splitVal;
extern splitNode splits[MAX_SPLITS];
extern int doLC;

int
mainPI (void)
{
    int i, splitRet;

    if (mkfifo (fifo, 0666) == -1)
    {
        if (errno != EEXIST)
            return fatal(   "ERROR: mkfifo failed.\n"
                            "SOLUTION: Check server's mainPI.\n");

    }

    if ((fdpub = open (fifo, O_RDWR)) < 0)
        return fatal(   "ERROR: Fifo open failed.\n"
                        "SOLUTION: Check server's mainPI.\n");

    if ((i = getOnlineFreeID(NULL)) == -1)
        return fatal(   "ERROR: Can't get a free slot in split vec.\n"
                        "SOLUTION: Check MAX_SPLITS.\n");

    /* Handlers de SIGS */
    (void)signal(SIGINT, sighandLCPI);

    /* Actualizo online */
    modifyOnline(i, i, NULL, 1);

    /*Se splitea dependiendo de los parámetros.*/
    if (splitVal == 't')
        splitRet = split(listenPubPI, NULL, (void *)&splits[i].thread, splitVal,
                        endCiclesPI);
    else
        splitRet = split(listenPubPI, NULL, (void *)&splits[i].cID, splitVal,
                        endCiclesPI);

    if ( splitRet != 1)
        fatal(  "ERROR: Split failed.\n"
                "SOLUTION: Check SPLITS_QUANTITY.\n");

    readCommandsPI();

    if(close (fdpub))
        return fatal(   "ERROR: Closing public fifo.\n"
                        "SOLUTION: Check server's mainPI.\n");

    return 0;
}

void *
listenPubPI(void *parmsLC)
{
    char msgbuf[MSGSIZE+1] = {0};
    char *ptr = NULL;
    int cliID = 0, move = 0, splitRet;
    fd_set master_set, working_set;
    char ch;
    char params[50] = {0};
    char priv[50] = {0};
    char full[100] = {0};
    int size, com;
    struct timeval tw, tm;

    tm.tv_sec  = SEC_TIMEOUT;
    tm.tv_usec = 0;
    FD_ZERO(&master_set);
    FD_SET(fdpub, &master_set);

    while(doLC)
    {
        memcpy(&working_set, &master_set, sizeof(master_set));
        memcpy(&tw, &tm, sizeof(struct timeval));

        if( select(fdpub + 1, &working_set, (fd_set *)0, (fd_set *)0, &tw) < 0)
        {
            if (errno == EINTR)
            {
                exitSplit(splitVal);
            }
            else
                fatal(  "ERROR: Select failed.\n"
                        "SOLUTION: Check server's listenPubPI.\n");
        }

        if (FD_ISSET (0, &working_set))
        {
            read(0, &ch, 1);
            printf("%c\n", ch);
        }

        if (FD_ISSET (fdpub, &working_set))
        {

            if (read (fdpub, msgbuf, MSGSIZE+1) < 0)
                fatal(  "ERROR: message read failed.\n"
                        "SOLUTION: Check server's listenPubPI.\n");

            move = readIDPI(msgbuf, &cliID );
            ptr = strdup(msgbuf);

            /* HACK: Si id=0 no esta loggeado, no puedo splittear
                    Entonces llamo a waitPck sin splittear */
            if (cliID == 0)
                waitPckPI((void *)ptr);
            else if (!isFreeOnline(cliID))
            {
                sndFifoAns(priv, IS_BUSY);
            }
            else
            {
                clrtext(full, 100);
                clrtext(params, 50);
                clrtext(priv, 50);
                sscanf(msgbuf + move, "%d,%d,%s", &com, &size,full);

                full[size] = 0;

                getparamsPI(full, params, priv);

                /* Me fijo si es un commit.
                Si es, creo el .new para evitar conflictos. */

                if (canCommittPI(msgbuf + move))
                {
                    /* Actualizo online */
                    modifyOnline(cliID, cliID, NULL, 1);

                    /*Se splitea dependiendo de los parámetros.*/
                    if (splitVal == 't')
                        splitRet = split(waitPckPI, (void *)ptr,
                                (void *)&splits[cliID].thread, splitVal, NULL);
                    else
                        splitRet = split(waitPckPI, (void *)ptr,
                                (void *)&splits[cliID].cID, splitVal, NULL);

                    if ( splitRet != 1)
                    {
                        fatal(  "ERROR: listenPubPI Split failed.\n"
                                "SOLUTION: Check MAX_SPLITS.\n");
                        doLC = 0;
                    }

                }
            }
        }
    }
    return (void *)NULL;
}

void readCommandsPI(void)
{
    int i;
    char command[MAX_COMMAND_LEN+1] = {0};
    char * param;
    char * commands[] = {"registrar", "usuarios", "dir", "last10",
                        "ulast10", "newDir", "salir"};
    int cant_comms = sizeof(commands) / sizeof(commands[0]);

    void (*pFunct[]) (char *)= {registrar, usuarios, dir, last10, ulast10,
                                newDir, salirPI};

    fprintf (stdout, "\n<>: ");
    getLine (command, MAX_COMMAND_LEN, stdin);

    for (i=0 ; i < cant_comms+1 ; i++)
    {
        if (i == cant_comms)
        {
           fprintf (stdout, "\nError: Invalid command\n<>: ");
           getLine (command, MAX_COMMAND_LEN, stdin);
           i = -1;
        }
        else if (strcmp (command, commands[i]) == 0)
        {
            if(i == 6)
                salirPI(param);

            pFunct[i] (param);
            fprintf (stdout, "\n<>: ");
            getLine (command, MAX_COMMAND_LEN, stdin);
            i = -1;
        }
    }

    return ;
}

void *
waitPckPI(void *ptr)
{
    int com;
    int size;
    int close = 1;
    char params[50] = {0};
    char priv[50] = {0};
    char full[100] = {0};
    char *msg = (char *)ptr;
    int move, cliID;

    move = readIDPI(msg, &cliID );

    if (cliID == 0)
        close = 0;

    sscanf(msg + move, "%d,%d,%s", &com, &size,full);

    full[size] = 0;

    getparamsPI(full, params, priv);

    switch(com)
    {
        case COM_NAME:
            (void)addnamePI(params, priv);
            break;

        case COM_LIST:
            listdirsPI(full);
            break;

        case COM_ADD:
            (void)adddirPI(params, priv, cliID);
            break;

        case COM_REMOVE:
            (void)removedirPI(params, priv);
            break;

        case COM_CLOSE:
            closesessPI(full);
            break;

        case COM_COMMIT:
            rcvCommitPI(params, priv);
            break;

        default:
            break;
    }

    free(ptr);

    if (close)
    {
        modifyOnline(cliID, cliID, NULL, 0);
        exitSplit(splitVal);
    }

    return (void *)NULL;
}

void salirPI(char * param)
{
    closeALLPI();
    return;
}

int addnamePI(char * name, char * priv)
{
    char answ[MSGSIZE+1] = {0};
    int len = 0;
    int cliID, fd;

    if (addUser(name, priv) == DB_INTERNAL_ERROR)
    {
        sndFifoAns(priv, COM_ERR);
        return fatal(   "ERROR: Database error In addname.\n"
                        "SOLUTION: Check Database status.\n");
    }

    switch(DBconnect(name))
    {
        case DB_INTERNAL_ERROR:
            sndFifoAns(priv, COM_ERR);
            return fatal(   "ERROR: Database error In addname.\n"
                            "SOLUTION: Check Database status.\n");
            break;

        case DB_ALREADY_EXISTS:
            sndFifoAns(priv, COM_ERR);
            fprintf(stderr, "ERROR: User %s already logged\n", name);
            return fatal(   "SOLUTION: If this persist, ban him. :)\n");
            break;

        case DB_NO_SLOTS:
            sndFifoAns(priv, COM_ERR);
            return fatal(   "ERROR: No more slots available.\n"
                            "SOLUTION: Check MAX_SPLITS.\n");
            return -1;
            break;

        default:
            break;
    }

    cliID = userID(name);
    sprintf(answ, "%d,%d", COM_ACK, cliID);

    len = strlen((char *)answ);

    if ((fd = open(priv, O_WRONLY)) < 0)
    {
        fatal(  "ERROR: Fifo open failed.\n"
                "SOLUTION: Check client status.\n");
    }

    send_data_fifo (fd, answ, len+1);

    addLog(priv, "Logged in");

    close(fd);
    return 1;

}

void adddirPI(char * dir, char * priv, int cliID)
{
    char serv_priv[50] = {0};
    char answ[50] = {0};
    int fdserv, len, fd, back, resp, size = 0;
    char path[MAX_DIR_LEN + 7] = {0};
    char logact[100] = {0};

    queueADT dirs;
    int qlen, flag = 1;
    char *aux_dir;
    char cliPriv[MSGSIZE+1] = {0};

    dirs = listDir();
    qlen = queueLength(dirs);


    if(isSynched(cliID, dir))
    {
        sndFifoAns(priv, IS_SYNC);
        return;
    }

    while (qlen-- && flag)
    {
        aux_dir = (char *)dequeue ( dirs );
        if (strcmp(dir, aux_dir) == 0)
            flag = 0;

        free(aux_dir);
    }
    if (flag)
    {
        sndFifoAns(priv, DIR_ERR);
        return;
    }

    sprintf(serv_priv, "%s.serv", priv);
    len = strlen((char *)serv_priv);
    len += strlen(dir);
    len += 1;
    sprintf(answ, "%d,%d,%s,%s", COM_SND_FILES, len, serv_priv, dir);

    len = strlen((char *)answ);

    if ((fd = open(priv, O_WRONLY)) < 0)
        fatal(  "ERROR: fifo open failed.\n"
                "SOLUTION: Check server's adddirPI.\n");

    if (mkfifo (serv_priv, 0666) == -1)
    {
        if (errno != EEXIST)
        {
            sndFifoAns(priv, COM_ERR);
            fatal(  "ERROR: mkfifo failed.\n"
                    "SOLUTION: Check server's adddirPI.\n");
        }
    }

    send_data_fifo (fd, answ, len);

    back = readcomChPI(serv_priv);

    resp = addFifoDir(priv,dir);

    if ((fdserv = open(serv_priv, O_RDONLY)) < 0)
        fatal(  "ERROR: fifo open failed.\n"
                "SOLUTION: Check server's adddirPI.\n");

    size = readsize(fdserv);

    if (read (fdserv, cliPriv, size) < 0)
        fatal(  "ERROR: message read failed.\n"
                "SOLUTION: Check server's adddirPI.\n");

    sprintf (path, "./%s", dir);
    if (walkDirPI(path, "", cliPriv, serv_priv) <= 0)
        fatal(  "ERROR: Dir send failed.\n"
                "SOLUTION: Check server's adddirPI.\n");

    sndFifoAns(cliPriv, COM_END);

    strcpy (logact, "Sync dir: ");
    strcat(logact, dir);
    addLog(priv, logact);

    close(fd);
    close(fdserv);

    return;
}

void removedirPI(char * dir, char * priv)
{
    DB_ERR ans;
    char logact[100] = {0};
    int len, fd;
    char answ[MSGSIZE] = {0};


    if ((fd = open(priv, O_WRONLY)) < 0)
        fatal(  "ERROR: fifo open failed.\n"
                "SOLUTION: Check server's removedirPI.\n");

    if ((ans = removeDirByFifo(priv, dir)) != DB_SUCCESS)
    {
        sndFifoAns(priv, COM_ERR);
        fatal(  "ERROR: DB failure.\n"
                "SOLUTION: Check server's removedirPI.\n");
    }

    len = strlen(dir);
    sprintf(answ, "%d,%d,%s", COM_RMV_OK, len, dir);
    len = strlen(answ);

    send_data_fifo (fd, answ, len);

    strcpy (logact, "Remove sync: ");
    strcat(logact, dir);
    addLog(priv, logact);

    close(fd);

    return;
}

void listdirsPI(char * priv)
{
    char serv_priv[50] = {0};
    char answ[50] = {0};
    int len, fd, fdp;
    int size, fdserv, nwrite;
    char cliPriv[MSGSIZE+1] = {0};

    sprintf(serv_priv, "%s.serv", priv);
    len = strlen (serv_priv);
    sprintf(answ, "%d,%d,%s", COM_SND_DIRLIST, len, serv_priv);

    len = strlen((char *)answ);

    if (mkfifo (serv_priv, 0666) == -1)
    {
        if (errno != EEXIST)
            fatal(  "ERROR: mkfifo failure.\n"
                    "SOLUTION: Check server's listdirsPI.\n");
    }

    if ((fd = open(priv, O_RDWR )) < 0)
        fatal(  "ERROR: open fifo failure.\n"
                "SOLUTION: Check server's listdirsPI.\n");


    if ((nwrite = write(fd, answ, len)) == -1)
        fatal(  "ERROR: message sent failure.\n"
                "SOLUTION: Check server's listdirsPI.\n");


    if (rcvFifoAns(serv_priv) != COM_ACK)
        fatal(  "ERROR: message failure.\n"
                "SOLUTION: Check server's listdirsPI.\n");

    if ((fdserv = open(serv_priv, O_RDONLY)) < 0)
        fatal(  "ERROR: open fifo failure.\n"
                "SOLUTION: Check server's listdirsPI.\n");

    size = readsize(fdserv);

    if (read (fdserv, cliPriv, size) < 0) /* es bloqueante? */
        fatal(  "ERROR: message failure.\n"
                "SOLUTION: Check server's listdirsPI.\n");

    if ((fdp = open(cliPriv, O_RDWR )) < 0)
        fatal(  "ERROR: open fifo failure.\n"
                "SOLUTION: Check server's listdirsPI.\n");

    if (sndlistPI(cliPriv, fdp, serv_priv) < 0)
        fatal(  "ERROR: List couldn't be send correctly.\n"
                "SOLUTION: Check server's listdirsPI.\n");

    addLog(priv, "List dirs");

    close (fd);
    close (fdserv);

    return;
}

void closesessPI(char * priv)
{
    DB_ERR ans;

    if ((ans = disconnectFifo(priv)) != DB_SUCCESS)
    {
        sndFifoAns(priv, COM_ERR);
        fatal(  "ERROR: DB failure.\n"
                "SOLUTION: Check server's closesessPI.\n");

    }

    addLog(priv, "Logged Out");

    return;
}

void getparamsPI(char * full, char * params, char * priv)
{
    char c;

    c = *full++;
    while (c != ',' && c != 0)
    {
        *priv++ = c;
        c = *full++;
    }
    if (c == 0)
        return ;

    strcpy(params, full);
    return;
}

int sndlistPI(char * priv, int fdpriv, char * serv_priv)
{
    queueADT dirs;
    int fdserv, cant;
    int name_len, tot_len;

    char answ[MSGSIZE + 1] = {0};
    int back;

    char * name;

    if ((fdserv = open (serv_priv, O_RDONLY)) < 0)
        fatal(  "ERROR: open fifo failure.\n"
                "SOLUTION: Check server's sndlistPI.\n");

    dirs = listDir();
    cant = queueLength(dirs);

    if (close(fdserv) < 0)
        fatal(  "ERROR: close fifo failure.\n"
                "SOLUTION: Check server's sndlistPI.\n");

    while (cant--)
    {
        name = (char *)dequeue ( dirs );
        name_len = strlen( name);
        sprintf(answ, "%d,%d,%s", SND_DIR_NAME, name_len, name);

        tot_len = strlen (answ);

        do
        {
            if ((send_data_fifo (fdpriv, answ, tot_len)) < 0)
                return fatal(   "ERROR: send dir failed.\n"
                                "SOLUTION: Check server's sndlistPI.\n");

            back = rcvFifoAns(serv_priv);

        }while (back != COM_ACK);
    }

    freeQueue( dirs );
    sndFifoAns(priv, COM_END);

    return 1;
}

void rcvCommitPI(char * params, char * priv)
{
    char serv_priv[50] = {0};
    char answ[50] = {0};
    char buffer[BUF_SIZE] = {0};
    int nread, len, fd, fdserv, size;
    int path_size, comm, type;
    char newpath[100] = {0};
    FILE * pfile;
    char path[100] = {0};
    char msgbuf[100] = {0};
    char logact[100] = {0};
    char dir[FILE_LEN] = {0};
    char cliPriv[MSGSIZE+1] = {0};

    getDirType(params, dir, &type);


    if (type == ADD_MOD)
    {
        sprintf(serv_priv, "%s.serv", priv);
        len = strlen((char *)serv_priv);
        len += strlen(dir);
        len += 1;
        sprintf(answ, "%d,%d,%s,%s", COM_RCV_COMMIT, len, serv_priv, dir);

        len = strlen((char *)answ);

        if ((fd = open(priv, O_WRONLY)) < 0)
            fatal(  "ERROR: open fifo failure.\n"
                    "SOLUTION: Check server's rcvCommitPI.\n");

        if (mkfifo (serv_priv, 0666) == -1)
        {
            if (errno != EEXIST)
            {
                sndFifoAns(priv, COM_ERR);
                fatal(  "ERROR: mkfifo failure.\n"
                        "SOLUTION: Check server's rcvCommitPI.\n");
            }
        }

        if( (send_data_fifo (fd, answ, len)) < 0 )
            fatal(  "ERROR: send data failed.\n"
                    "SOLUTION: Check server's rcvCommitPI.\n");

        if ((fdserv = open (serv_priv, O_RDONLY)) < 0)
            fatal(  "ERROR: open fifo failure.\n"
                    "SOLUTION: Check server's rcvCommitPI.\n");

        comm = readcom (fdserv);
        size = readsize(fdserv);

        if (read (fdserv, cliPriv, size) < 0)
            fatal(  "ERROR: message read failed.\n"
                    "SOLUTION: Check server's rcvCommitPI.\n");

        sndFifoAns(cliPriv, COM_ACK);
        comm = readcom (fdserv);

        if (comm == SND_FILE)
        {
            path_size = readsize (fdserv);

            if (read (fdserv, msgbuf, path_size) < 0)
                fatal(  "ERROR: message read failed.\n"
                        "SOLUTION: Check server's rcvCommitPI.\n");

            msgbuf[path_size] = 0;
            sscanf (msgbuf, "%d,%s", &size, path);
            sprintf(newpath, "%s.new", path);


            if (size == -1)
            {
                if(mkdir(path, 0777) == -1)
                {
                    printf("ERROR: creating dir: %s\n", path);
                    sndFifoAns(cliPriv, COM_ERR);
                    return ;
                }
                if (remove(newpath) != 0)
                {
                    printf("ERROR: removing dir: %s\n", newpath);
                    sndFifoAns(priv, COM_ERR);
                    return ;
                }
                sndFifoAns(cliPriv, COM_ACK);
            }
            else
            {
                if((pfile = fopen(newpath, "w")) == NULL)
                    fatal(  "ERROR: creating file.\n"
                            "SOLUTION: Check server's rcvCommitPI.\n");

                nread = 0;
                sndFifoAns(cliPriv, COM_ACK);

                while (size > 0)
                {
                    if (size >= BUF_SIZE)
                            nread = BUF_SIZE;
                    else
                            nread = size;

                    if (read (fdserv, buffer, nread) < 0)
                    {
                        sndFifoAns(cliPriv, COM_ERR);
                        fatal("msg read failed\n");
                    }

                    if ((fwrite(buffer, 1, nread, pfile)) < nread)
                    {
                        sndFifoAns(cliPriv, COM_ERR);
                        fatal("File write failed\n");
                    }

                    sndFifoAns(cliPriv, COM_ACK);

                    size -= nread;
                }

                if ((fclose (pfile)) == EOF)
                        fatal("file close failed\n");
                if (rename(newpath, path) != 0)
                {
                    printf("Error renaming %s\n", newpath);
                    return;
                }
            }

        }

        if ((close (fdserv)) < 0)
            fatal("file close failed\n");



        if (srv_commitPI(priv, serv_priv, path, type) < 0)
        {
            printf("Error forwarding %s\n", path);
        }

        strcpy(logact, "Commited (add/mod): ");
        strcat (logact, path);

        addLog(priv, logact);
        sndFifoAns(cliPriv, COM_ACK);

    }
    else if(type == DEL_COMMIT)
    {
        if (remove(dir) != 0)
        {
            sndFifoAns(priv, COM_ERR);
        }
        else
        {
            if (srv_commitPI(priv, serv_priv, dir, type) < 0)
            {
                printf("Error forwarding %s\n", path);
            }

            strcpy(logact, "Commited (del): ");
            strcat (logact, dir);

            addLog(priv, logact);

            sndFifoAns(priv, COMMIT_OK);
        }
    }
    else if(type == DEL_DIR_COMMIT)
    {
        if (rmdir(dir) != 0)
        {
            sndFifoAns(priv, COM_ERR);
        }
        else
        {
            if (srv_commitPI(priv, serv_priv, dir, type) < 0)
            {
                printf("Error forwarding %s\n", path);
            }

            strcpy(logact, "Commited (dir del): ");
            strcat (logact, dir);

            addLog(priv, logact);

            sndFifoAns(priv, COMMIT_OK);
        }

    }

    return;
}

int srv_commitPI(char * priv, char * serv_priv, char * path, int type)
{
    queueADT clients;
    int fdserv, cant;
    int back;
    char * fifo_name;
    char dir[MAX_DIR_LEN] = {0};
    int len, fd;
    char answ[100] = {0};
    char aux_msg[100] = {0};
    int size = 0;
    char cliPriv[MSGSIZE+1] = {0};
    int cliID = 0;


    getDir (dir, path);
    clients = listUpdate(priv, dir);
    cant = queueLength(clients);

    while (cant--)
    {
        fifo_name = (char *)dequeue ( clients );

        cliID = userIDPI(fifo_name);
        while (!isFreeOnline(cliID))
            sleep(5);
        sprintf(serv_priv, "%s.serv", fifo_name);
        sprintf(aux_msg, "%s,%s,%d", serv_priv, path, type);
        len = strlen((char *)aux_msg);
        sprintf(answ, "%d,%d,%s", COM_SND_COMMIT, len, aux_msg);

        len = strlen((char *)answ);

        if ((fd = open(fifo_name, O_WRONLY)) < 0)
        {
            fatal ("fifo open failed\n");
        }

        if (mkfifo (serv_priv, 0666) == -1)
       {
           if (errno != EEXIST)
           {
               sndFifoAns(priv, COM_ERR);
               fatal ("receiver: mkfifo\n");
           }
       }

        send_data_fifo (fd, answ, len);

        if ((fdserv = open (serv_priv, O_RDONLY)) < 0)
            fatal ("fifo open failed\n");

        back = readcom(fdserv);
        size = readsize(fdserv);

        clrtext(cliPriv, MSGSIZE+1);
        if (read (fdserv, cliPriv, size) < 0)
            fatal ("msg read failed\n");

        close(fdserv);

        if (type == ADD_MOD)
        {
            if (snd_file_fifo (cliPriv, serv_priv, path, 0) < 0)
            {
                printf("%s not sent to %s\n", path, cliPriv);
            }
        }

    }

    freeQueue( clients );

    return 1;
}

int canCommittPI(char * msg)
{
    FILE * pfile;
    int com;
    int size;
    char params[50] = {0};
    char priv[50] = {0};
    char full[100] = {0};
    int type, fd;
    char dir[FILE_LEN] = {0};
    char newpath[100] = {0};
    int len;
    char answ[FILE_LEN] = {0};

    sscanf(msg, "%d,%d,%s", &com, &size,full);

    if (com != COM_COMMIT)
        return 1;

    full[size] = 0;

    getparamsPI(full, params, priv);
    getDirType(params, dir, &type);

    sprintf(newpath, "%s.new", dir);

    if((pfile = fopen(newpath, "r")) == NULL)
    {
        if (type == DEL_COMMIT)
            return 1;
        if (type == DEL_DIR_COMMIT)
            return 1;

        if((pfile = fopen(newpath, "w")) == NULL)
        {
            fatal ("file open failed\n");
            return -1;
        }

        if (fclose(pfile) == EOF)
        {
            fatal ("file close failed\n");
            return -1;
        }
        return 1;

    }

    if ((fd = open(priv, O_WRONLY)) < 0)
    {
        fatal ("fifo open failed\n");
        return -1;
    }

    /* Log Conflict */
    char logInfo[MAX_DIR_LEN*2]={0};
    sprintf(logInfo, "Conflict when committing %s @", dir);
    addLog(priv, logInfo);

    len = strlen(dir);
    sprintf(answ, "%d,%d,%s", WILL_UPDATE, len, dir);

    len = strlen((char *)answ);
    send_data_fifo (fd, answ, len);

    close(fd);


    return 0;
}

void
sighandLCPI(int signo)
{
    closeALLPI();
}

void
endCiclesPI(int signo)
{
    doLC = 0;
    return;
}

void
closeALLPI(void)
{
    queueADT q = NULL;
    int *index = NULL;
    int stat;
    queueADT fifos;
    char *fifo_name;
    int cant = 0;
    char fifoPath[MAX_FIFO_LEN] = {0};

    printf("Closing splits.");
    doLC = 0;

    if (splitVal == 't')
    {
        q = getUsedOnline();

        while((index = dequeue(q)) != NULL)
        {
            pthread_join(splits[*index].thread, NULL);
             printf(".");
            free(index);
        }
        freeQueue(q);
    }
    else
    {
        /*HACK: Mando senial para salir del select*/
        kill(splits[0].cID, SIGUSR1);
        while ((waitpid (-1, &stat, 0)) > 0)
            printf(".");
    }

    fifos = getFifos();
    cant = queueLength(fifos);

    while (cant--)
    {
        fifo_name = dequeue(fifos);
        sprintf(fifoPath, "%s", fifo_name);
        remove(fifoPath);
        sprintf(fifoPath, "%sP", fifo_name);
        remove(fifoPath);
        sprintf(fifoPath, "%s.serv", fifo_name);
        remove(fifoPath);
        free(fifo_name);
    }
    freeQueue(fifos);
    sprintf(fifoPath, "/tmp/public");

    remove(fifoPath);
    printf("\nServer closed\n");
    exitSplit(splitVal);
}

int readIDPI(char * msgbuf, int * cliID )
{
    char chsize[17] = {0};
    int i = 0;

    chsize[i] = msgbuf[i];

    while (chsize[i] != 0 && chsize[i] != ',')
    {
        i++;
        chsize[i] = msgbuf[i];
    }

    chsize[i] = 0;
    sscanf (chsize, "%d", cliID);

    return i+1;
}
